package cn.tedu.knows.faq.service.impl;


import cn.tedu.knows.commons.exception.ServiceException;
import cn.tedu.knows.commons.model.*;
import cn.tedu.knows.faq.kafka.QuestionProducer;
import cn.tedu.knows.faq.mapper.QuestionMapper;
import cn.tedu.knows.faq.mapper.QuestionTagMapper;
import cn.tedu.knows.faq.mapper.UserQuestionMapper;
import cn.tedu.knows.faq.service.IQuestionService;
import cn.tedu.knows.faq.service.ITagService;
import cn.tedu.knows.faq.vo.QuestionVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author tedu.cn
 * @since 2021-05-25
 */
@Service
@Slf4j
public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question> implements IQuestionService {


    @Autowired
    private QuestionMapper questionMapper;

    @Override
    public PageInfo<Question> getMyQuestions(String username,
                                             Integer pageNum, Integer pageSize) {
        //1.按用户名查询当前登录用户对象
        User user=getUser(username);
        log.debug("当前登录用户:{}",user);
        //2.根据当前登录用户信息,查询当前登录用户提出的问题
        QueryWrapper<Question> query=new QueryWrapper<>();
        // 查询条件1:必须是当前登录用户提问的问题
        query.eq("user_id",user.getId());
        // 查询条件2:必须是没有被删除的问题才能查询出来
        query.eq("delete_status",0);
        // 根据问题的提问时间
        query.orderByDesc("createtime");
        //PageHelper.startPage能够使紧随其后执行的一次sql查询
        //自动生成指定的分页limit语句
        //方法的第一个参数是页码,从1开始,第二个参数是每页条数
        PageHelper.startPage(pageNum,pageSize);
        //3.执行查询并返回
        List<Question> list=questionMapper.selectList(query);
        log.debug("查询到问题的数量为:{}",list.size());
        //4.遍历所有问题,将每个问题的对应的标签获得出来
        //  并赋值给当前问题的tags属性
        for(Question q: list){
            //根据tagNames获得List<Tag>
            List<Tag> tags=tagNames2Tags(q.getTagNames());
            //将tags赋值到question对象中
            q.setTags(tags);
        }
        //别忘了返回!!!
        //new PageInfo<>(list)表示实例化一个PageInfo对象
        //list是构造方法的参数
        //PageInfo内部实例化时会自动赋值分页信息
        //list参数会赋值到PageInfo list属性中
        return new PageInfo<>(list);
    }

    @Autowired
    private ITagService tagService;

    //根据tagNames属性获得对应标签的集合List<Tag>
    private List<Tag> tagNames2Tags(String tagNames){
        //tagNames:"java基础,javaSE,面试题"
        String[] names=tagNames.split(",");
        //names:{"java基础","javaSE","面试题"}
        //赋值准备工作
        //1.实例化一个List集合保存获得出来的Tag对象
        List<Tag> tags=new ArrayList<>();
        //2.从TagService获得包含所有标签的Map集合,用于取值
        Map<String,Tag> name2TagMap=tagService.name2TagMap();
        for(String name:names){
            tags.add(name2TagMap.get(name));
        }
        //千万别忘了返回
        return tags;
    }
    @Autowired
    private UserQuestionMapper userQuestionMapper;
    @Autowired
    private QuestionTagMapper questionTagMapper;

    @Resource
    private QuestionProducer questionProducer;

    @Override
    //开启Spring声明式事务
    //这个方法中的所有对数据库的操作,要么都执行,要么都不执行
    @Transactional
    public void saveQuestion(QuestionVo questionVo, String username) {
        //1.获得当前登录用户信息
        User user=getUser(username);
        log.debug("当前登录用户信息:{}",user);
        //2.根据用户选择的标签拼接一个tagNames列的值
        StringBuilder builder =new StringBuilder();
        for(String tagName: questionVo.getTagNames()){
            builder.append(tagName).append(",");
        }
        //"java基础,javaSE,面试题"
        String tagNames=
        builder.deleteCharAt(builder.length()-1).toString();
        log.debug("本次新增的问题标签字符串:{}",tagNames);
        //3.实例化Question对象并收集信息
        Question question=new Question()
                .setTitle(questionVo.getTitle())
                .setContent(questionVo.getContent())
                .setUserId(user.getId())
                .setUserNickName(user.getNickname())
                .setCreatetime(LocalDateTime.now())
                .setTagNames(tagNames)
                .setStatus(0)
                .setPageViews(0)
                .setPublicStatus(0)
                .setDeleteStatus(0);
        //4.执行question的新增
        int num=questionMapper.insert(question);
        if(num!=1){
            throw new ServiceException("新增时报错!");
        }
        log.debug("新增问题信息为:{}",question);

        //5.新增question对象和tag的关系表数据
        //获得包含所有标签的Map
        Map<String,Tag> name2TagMap=tagService.name2TagMap();
        for(String tagName: questionVo.getTagNames()) {
            //根据标签名称获得标签对象
            Tag tag = name2TagMap.get(tagName);
            QuestionTag questionTag = new QuestionTag()
                    .setQuestionId(question.getId())
                    .setTagId(tag.getId());
            //新增问题和标签的关系
            num = questionTagMapper.insert(questionTag);
            if (num != 1) {
                throw new ServiceException("新增时报错!");
            }
            log.debug("新增关系成功:{}", questionTag);
        }

        //6.新增question对象和user的关系表数据
        //获得包含当前所有讲师的Map
        //使用Ribbon调用获得所有老师的数组
        String url="http://sys-service/v1/users/master";
        User[] users=restTemplate.getForObject(url,
                    User[].class);
        //实例化map集合保存所有讲师信息
        Map<String,User> teacherMap=new HashMap<>();
        for(User u:users){
            teacherMap.put(u.getNickname(),u);
        }


        for(String nickname: questionVo.getTeacherNicknames()){
            User teacher=teacherMap.get(nickname);
            UserQuestion userQuestion=new UserQuestion()
                    .setQuestionId(question.getId())
                    .setUserId(teacher.getId())
                    .setCreatetime(LocalDateTime.now());
            num=userQuestionMapper.insert(userQuestion);
            if(num!=1){
                throw new ServiceException("新增时报错!");
            }
            log.debug("新增了关系:{}",userQuestion);
        }
        //发送消息(将question发送到kafka)
        questionProducer.sendQuestion(question);
    }

    @Override
    public Integer countQuestionByUserId(Integer userId) {
        QueryWrapper<Question> query=new QueryWrapper<>();
        query.eq("user_id",userId);
        query.eq("delete_status",0);
        Integer count=questionMapper.selectCount(query);
        // 别忘了返回count
        return count;
    }

    @Override
    public PageInfo<Question> getTeacherQuestions(
                    String username, Integer pageNum,
                                    Integer pageSize) {
        User user=getUser(username);
        PageHelper.startPage(pageNum,pageSize);
        List<Question> questions= questionMapper
                      .findTeacherQuestions(user.getId());
        //将所有查询出来的问题添加标签集合
        for(Question q:questions){
            List<Tag> tags=tagNames2Tags(q.getTagNames());
            q.setTags(tags);
        }
        //将List转换为PageInfo返回
        return new PageInfo<>(questions);
    }

    @Override
    public Question getQuestionById(Integer id) {
        //按id查询Question的基本信息
        Question question=questionMapper.selectById(id);
        //根据当前问题的tagNames列值获得Tag的List
        List<Tag> tags=tagNames2Tags(question.getTagNames());
        question.setTags(tags);
        //别忘了返回!!!!
        return question;
    }



    @Resource
    private RestTemplate restTemplate;

    //使用Ribbon调用用户名查询用户对象的方法
    public User getUser(String username){
        String url="http://sys-service/v1/auth/user?username={1}";
        User user=restTemplate.getForObject(url,
                User.class,username);
        return user;
    }

    @Override
    public PageInfo<Question> getQuestions(
            Integer pageNum, Integer pageSize) {
        //分页指令
        PageHelper.startPage(pageNum,pageSize);
        List<Question> list=questionMapper
                .selectList(null);
        return new PageInfo<>(list);
    }



}
